define(function(require, exports, module) {
  var THREE = require('three');
  
  require('http://localhost/d/threejs-0.106.2/examples/js/libs/stats.min.js');
  require('http://localhost/d/threejs-0.106.2/examples/js/controls/OrbitControls.js');
  
  var { GUI } = require('http://localhost/d/threejs-0.106.2/examples/js/libs/dat.gui.min.js');
  
  const { Stats } = window
  const { OrbitControls } = THREE
  
  class BaseThreeApp {
    constructor(el, fn) {
      
      this.el = el;
      
      this.w = el.clientWidth || 960;
      this.h = el.clientHeight || 540;
      this.aspect = this.w / this.h;
      
      this.params = {
        time: 0
      }
      
      if (fn && fn.callBefore) {
        fn.callBefore.call(this)
      }
      
      this.initScene();
      this.initCamera();
      this.initLight();
      
      this.initRenderer();
      el.appendChild(this.renderer.domElement);
      
      var controls = new OrbitControls( this.camera, this.renderer.domElement );
      controls.maxPolarAngle = Math.PI * 0.5;
      controls.minDistance = 1000;
      controls.maxDistance = 5000;
      
      this.stats = new Stats();
      el.appendChild(this.stats.dom );
      
      var gui = new GUI();
      gui.add( this.params, 'time' );
      
    }
     
    initScene() {
      if (!this.scene) {

        this.scene = new THREE.Scene()

        let axesHelper = new THREE.AxesHelper(500);
        this.scene.add(axesHelper);

        var helper = new THREE.GridHelper(1000, 10);
//         helper.rotation.x = Math.PI / 2; //默认不是x,y平面
        helper.material.opacity = 0.25;
        helper.material.transparent = true;
        this.scene.add(helper);
      }

      return this.scene;
    }

    initCamera() {
      
      if (!this.camera) {
        this.camera = new THREE.PerspectiveCamera( 30, this.aspect, 1, 10000 );

//           var helper = new THREE.CameraHelper(this.camera);
//           this.scene.add(helper);
      }
      this.camera.position.set( 600, 400, 800 );
      return this.camera;
    }

    initLight() {
      if (!this.light) {
        this.light = new THREE.AmbientLight(0xffffff);
        this.light.position.set(100, 100, 100)
        this.scene.add(this.light)
      }

      if (!this.drLight) {
        this.drLight = new THREE.DirectionalLight(0xffffff, 1);
        this.drLight.position.set( 50, 200, 100 );
        this.drLight.position.multiplyScalar( 1.3 );

        this.scene.add(this.drLight)

      }
    }
    
    initRenderer() {
      if (!this.renderer) {
        this.renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
        this.renderer.setSize(this.w, this.h);
        // this.renderer.setClearColor(0x000000, 1.0);
        this.renderer.setPixelRatio(window.devicePixelRatio)

        // this.renderer.shadowMap.enabled = true;
        // this.renderer.shadowMapType = THREE.PCFSoftShadowMap;
      } else {
        this.renderer.setSize(this.w, this.h)
      }
      return this.renderer;
    }

    step() {
      
      if (this.timer) {
        cancelAnimationFrame(this.timer)
      }
      this.timer = requestAnimationFrame(() => { this.step() });
      
      this.render()

      if (this.params.time >= 0) {
        this.t = this.params.time
      } else {
        this.t += 16.67;
      }

      if (this.t > 120000) {
        this.t = 0;
      }
    }
    
    render() {
      this.renderer.render(this.scene, this.camera);
      this.stats.update();
    }
    
    
  }
  
  
  return BaseThreeApp
})